/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "utils_log_c.h"
#include <spdlog/spdlog.h>
#include <cstdarg>
#include <string>

namespace {
    // 使用printf风格格式化的通用日志函数
    void log_message(spdlog::level::level_enum level, const char* file, int line, 
                    const char* func, const char* fmt, va_list args) {
        if (!fmt) return;
        
        try {
            // 计算所需的缓冲区大小
            va_list args_copy;
            va_copy(args_copy, args);
            const int size = vsnprintf(nullptr, 0, fmt, args_copy);
            va_end(args_copy);
            
            if (size > 0) {
                // 分配缓冲区并格式化字符串
                std::string message(size, '\0');
                vsnprintf(message.data(), size + 1, fmt, args);
                // 使用spdlog记录日志
                spdlog::default_logger()->log(spdlog::source_loc{file, line, func}, level, message);
            } else {
                // 如果没有参数，直接输出格式字符串
                spdlog::default_logger()->log(spdlog::source_loc{file, line, func}, level, fmt);
            }
        } catch (...) {
            // 异常情况下直接输出原始格式字符串
            spdlog::default_logger()->log(spdlog::source_loc{file, line, func}, level, fmt);
        }
    }
}

extern "C" {

void c_log_trace(const char* file, int line, const char* func, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    log_message(spdlog::level::trace, file, line, func, fmt, args);
    va_end(args);
}

void c_log_debug(const char* file, int line, const char* func, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    log_message(spdlog::level::debug, file, line, func, fmt, args);
    va_end(args);
}

void c_log_info(const char* file, int line, const char* func, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    log_message(spdlog::level::info, file, line, func, fmt, args);
    va_end(args);
}

void c_log_warn(const char* file, int line, const char* func, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    log_message(spdlog::level::warn, file, line, func, fmt, args);
    va_end(args);
}

void c_log_error(const char* file, int line, const char* func, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    log_message(spdlog::level::err, file, line, func, fmt, args);
    va_end(args);
}

void c_log_critical(const char* file, int line, const char* func, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    log_message(spdlog::level::critical, file, line, func, fmt, args);
    va_end(args);
}

}